package com.geovis.emergency.spd.redis;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.Set;
import java.util.concurrent.Callable;

/**
 * <p>
 * Redis工具类
 * </p>
 *
 * @author Lonsho
 * @version 1.0
 * @date 2022/6/10
 */
@Component
@AllArgsConstructor
public class RedisUtil {
    private static SpdRedis redis;
    private final SpdRedis spdRedis;

    @PostConstruct
    public void init(){
        redis =  spdRedis;
    }

    /**
     * 保存到缓存
     * @param key
     * @param value
     * @param <T>
     */
    public static <T> void set(String key,Object value){
        redis.set(key,value);
    }
    /**
     * 保存到缓存
     * @param key
     * @param params
     * @param value
     * @param <T>
     */
    public static <T> void set(String key,Object params,Object value){
        redis.set(StrUtil.format(key,params),value);
    }

    /**
     * 保存到缓存，支持设置时间
     * @param key
     * @param params
     * @param value
     * @param seconds
     * @param <T>
     */
    public static <T> void setEx(String key,Object params,Object value,Long seconds){
        redis.setEx(StrUtil.format(key,params),value,seconds);
    }

    /**
     * 保存到缓存，支持设置时间
     * @param key
     * @param params
     * @param value
     * @param duration
     * @param <T>
     */
    public static <T> void setEx(String key, Object params, Object value, Duration duration){
        redis.setEx(StrUtil.format(key,params),value,duration);
    }

    /**
     * 获取redis缓存
     * @param key
     * @param params
     * @param valueLoader
     * @param <T>
     * @return
     */
    public static <T> T get(String key, Object params, Callable<T> valueLoader){
        return get(StrUtil.format(key,params),valueLoader);
    }

    /**
     * 获取redis缓存
     * @param key
     * @param valueLoader
     * @param <T>
     * @return
     */
    public static <T> T get(String key, Callable<T> valueLoader){
        final T obj = redis.get(key);
        if (ObjectUtil.isNotNull(obj)){
            return obj;
        }
        else {
            try {
                final T call = valueLoader.call();
                if (ObjectUtil.isNull(call)){
                    redis.set(key,call);
                }
                return  call;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * 获取redis缓存
     * @param key
     * @param defaultValue 默认值
     * @param <T>
     * @return
     */
    public static <T> T get(String key, T defaultValue){
        final T obj = redis.get(key);
        if (ObjectUtil.isNotNull(obj)){
            return obj;
        }
        return defaultValue;
    }
    public static <T> T get(String key){
        final T obj = redis.get(key);
        if (ObjectUtil.isNotNull(obj)){
            return obj;
        }
        return null;
    }
    /**
     * 获取缓存
     * @param key
     * @param duration
     * @param valueLoader
     * @param <T>
     * @return
     */
    public static <T> T getEx(String key, Duration duration, Callable<T> valueLoader){
        final T obj = redis.get(key);
        if (ObjectUtil.isNotNull(obj)){
            return obj;
        }
        else {
            try {
                final T call = valueLoader.call();
                if (ObjectUtil.isNotNull(call)){
                    redis.setEx(key,call,duration);
                }
                return  call;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 获取缓存
     * @param key
     * @param params
     * @param duration
     * @param valueLoader
     * @param <T>
     * @return
     */
    public static <T> T getEx(String key,Object params, Duration duration, Callable<T> valueLoader){
        return getEx(StrUtil.format(key,params),duration,valueLoader);
    }
    public static boolean del(String key){
        return redis.del(key);
    }
    public static boolean delPattern(String pattern){
        Set<String> keys = redis.keys(pattern);
        for (String key : keys) {
             redis.del(key);
        }
        return true;
    }
    public static boolean del(String key,Object params){
        return redis.del(StrUtil.format(key,params));
    }
}
